package reflect;

import reflect.annotation.AutoRunClass;
import reflect.annotation.AutoRunMethod;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;

public class Test6 {
    public static void main(String[] args) throws Exception{
        //

        Class cls=Class.forName("reflect.Person");

        //1. Constructor 获取构造器
        /*Constructor c= cls.getConstructor();//获取无参构造器
        Constructor c1=cls.getConstructor(String.class);//获取String有参构造器
        Constructor c2=cls.getConstructor(String.class,int.class);//获取String,int有参构造器
        Constructor[] cs=cls.getConstructors();//获取所有构造器

        Object obj=c1.newInstance("要参数了");
        System.out.println("----------------------");*/
        //一个获取方法 Method
        /*Object obj=cls.newInstance();//无参构造器
        Method method=cls.getMethod("sing");//获取sing方法
        //执行
        method.invoke(obj);
        //获取所有方法
        Method[] methods=cls.getMethods();//array
        for (Method m:methods){
            System.out.println(m);
        }
        System.out.println("-------------------");
        //get returnValue 获取该方法的返回值
        Object returnValue =method.invoke(obj);
        //get returnType 获取该方法的返回值类型
        Class returnType=method.getReturnType();
        //get methodName 获取该方法的方法名
        String methodName=method.getName();
        //get parameterTypes 获取该方法的参数类型
        Class[] parameterTypes=method.getParameterTypes();
        //get parameterCount 获取该方法的参数个数
        int parameterCount =method.getParameterCount();
        //get modifier 获取该方法的修饰符
        int modifier=method.getModifiers();
        //int  对应 修饰符  ---> Modifier.Public(定义的常量) ...
*/
        //获取私有的方法和私有属性的演示 get+Declared+
        //get DeclaredMethod
        /*Method method=cls.getDeclaredMethod("hehe");
        method.setAccessible(true);//暴力反射,强行打开访问权限
        method.invoke(new Object());
        method.setAccessible(false);//关闭访问权限
        // get DeclaredMethods,DeclaredField,DeclaredFields,DeclaredConstructor...
        */
        // get Field
        //Field field=cls.getField("name");//获取不到
        /*Field field1= cls.getDeclaredField("age");
        field1.setAccessible(true);
        Object obj=cls.newInstance();
        Object value=field1.get(obj);
        System.out.println(value);
        field1.set(obj,9);
        System.out.println(obj);*/
        //获取类和方法是否带有注解,获取注解的属性值
        boolean mark=cls.isAnnotationPresent(AutoRunClass.class);

        //获取注解的属性值
        AutoRunClass annoclass= (AutoRunClass) cls.getAnnotation(AutoRunClass.class);
        System.out.println("value"+annoclass.value());
        Method method=cls.getMethod("sayHello");
        boolean mark1=method.isAnnotationPresent(AutoRunMethod.class);

        AutoRunMethod annomethod=method.getAnnotation(AutoRunMethod.class);

        System.out.println(annomethod.value());

        //获取方法中的参数是否带有注解
        /*Parameter[] parameters=method.getParameters();
        Parameter p1=parameters[0];
        boolean b1=p1.isAnnotationPresent(AutoRunMethod.class);
        System.out.println(b1);*/



















        /*doSome(1,"a","b","c");
        doSome(2,"a");
        System.out.println("-------------------");*/


    }
    //变长参数的演示
    public  static void doSome(int a,String... b){
        System.out.println(a);
        System.out.println(Arrays.toString(b));
    }
}

// getConstructor() 方法既可以获取无参构造器，也可以获取有参构造器，
/*
其内部实现原理是：利用Java的特性 变长参数 实现的
当为变长参数时，传入和接收的其实都是一个数组（统一修改为数组），所以可以传入任意个数的参数

变长参数: 语法 ... 变长参数名
使用规则：单独使用
        和普通参数一起使用时，必须放在最后
        传入参数的顺序必须和定义的顺序一致
变长参数的数组类型： 变长参数名.getClass()
 */
